import {operatorEqual, applier, operatorAdd} from './functional.js'
import {every, zip, makeContinuable, map, pipe, reduce, take} from './iterator.js'
import {serializeList} from './serializeList.js'
import type {Type} from './type.js'

export type PredicateSpecification = {
    name: string
    symbolOffset: number
    parameterTypes: Type[]
}

export function areEqual(specification1: PredicateSpecification, specification2: PredicateSpecification) {
    return specification1.name == specification2.name &&
        specification1.symbolOffset == specification2.symbolOffset &&
        specification1.parameterTypes.length == specification2.parameterTypes.length &&
        pipe(
            zip(specification1.parameterTypes, specification2.parameterTypes),
            every(applier(operatorEqual)),
        )
}

export function* serialize({name, symbolOffset, parameterTypes}: PredicateSpecification): Iterable<string> {
    const parameterIterator = pipe(
        parameterTypes,
        map(({name}) => name),
        makeContinuable,
    )

    yield* pipe(parameterIterator, take(symbolOffset), serializeList)

    if (symbolOffset > 0)
        yield ' '

    yield name

    if (parameterTypes.length > symbolOffset)
        yield ' '

    yield* serializeList(parameterIterator)
}

export const stringify = (specification: PredicateSpecification) =>
    pipe(specification, serialize, reduce(operatorAdd))
